#pragma once
#include <vector>
#include <string>
#include <map>
#include <fmod.hpp>

namespace bs
{
	class ISoundListener
	{
	public:
		virtual void OnSoundEnd(std::string name) = 0;
	};

	class Config;

	class SoundManager
	{
	public:
		SoundManager();
		~SoundManager();

		void AddSoundListener(const char* name, ISoundListener* listener);
		void DetachListener(ISoundListener* listener);

		void PlaySound(const char* name);

		void SetConfigFile(const char* file = "sound.ini");

		void Update();
		void Pause();
		void Resume();
		void Stop();

		void PlayBgMusic(const char* name);
		void PauseBgMusic();
		void ResumeBgMusic();
		void StopBgMusic();

		void EnableSoundEffect(bool enable) { this->enableSoundEffect = enable; }
		void EnableBgMusic(bool enable) { this->enableBgMusic = enable; }

		void SetVolume(int vol);
		void SetBgVolume(int vol);

		static FMOD_RESULT F_CALLBACK OnChannelEnd(FMOD_CHANNEL* channel, FMOD_CHANNEL_CALLBACKTYPE type, int command, unsigned int commanddata1, unsigned int commanddata2);

	private:
		struct SndUnit;
		SndUnit* PlaySound(const char* name, int loop, float volume);

	private:
		struct SndUnit
		{
			SndUnit(FMOD::Sound* s, FMOD::Channel* c) : sound(s), channel(c) {}
			~SndUnit() { channel->stop(); sound->release(); }

			FMOD::Sound* sound;
			FMOD::Channel* channel;
		};

	private:
		FMOD::System* system;
		Config* cfg;

		std::map<std::string, SndUnit*> sounds;
		SndUnit* bgMusic;
		std::string bgMusicName;

		std::multimap<std::string, ISoundListener*> listeners;

		bool enableSoundEffect;
		bool enableBgMusic;

		float volume;
		float bgVolume;
	};
}